package org.example.com.pattern.structure.decorator

import java.io.File

/**
 * 结构型模式-装饰者模式
 */
interface DataSource {
    fun writeData(data: String)
    fun readData(): String
}

class FileDataSource(private val fileName: String) : DataSource {
    override fun writeData(data: String) {
        println("FileDataSource writeData... ")
    }

    override fun readData(): String {
        println("FileDataSource readData... ")
        return ""
    }
}

open class DataSourceDecorator(dataSource: DataSource) : DataSource {
    protected val wrapper: DataSource = dataSource
    override fun writeData(data: String) {
        wrapper.writeData(data)
    }

    override fun readData(): String {
        return wrapper.readData()
    }
}

class EncryptionDecorator(dataSource: DataSource) : DataSourceDecorator(dataSource) {
    override fun writeData(data: String) {
        //进行加密
        super.writeData(data)
    }

    override fun readData(): String {
        //进行解密
        return super.readData()
    }
}

class CompressionDecorator(dataSource: DataSource) : DataSourceDecorator(dataSource) {
    override fun writeData(data: String) {
        //压缩数据
        super.writeData(data)
    }

    override fun readData(): String {
        //解压数据
        return super.readData()
    }
}

/**
 * 使用方式1
 *
 */
class Application {
    fun dumpUsageExample() {
        var source: DataSource = FileDataSource("a.txt")
        source.writeData("")

        source = CompressionDecorator(source)
        source.writeData("")

        EncryptionDecorator(source).writeData("")
    }
}

/**
 * 使用方式2
 * 客户端使用外部数据源
 */
class SalaryManager(private val source: DataSource) {
    fun load(): String {
        return source.readData()
    }

    fun save() {
        source.writeData("")
    }
}

fun main() {
    var source: DataSource = FileDataSource("a.txt")
    val enabledEncryption = true
    if (enabledEncryption) {
        source = EncryptionDecorator(source)
    }
    val enabledCompression = true
    if (enabledCompression) {
        source = CompressionDecorator(source)
    }
    SalaryManager(source).load()
}